<template>
  <div
    :class="animate"
    :style="{ height: height, width: width }"
    :id="chartOption.bindingDiv"
    ref="chartDiv"
  />
</template>

<script>
import echarts from "echarts";
require("echarts/theme/macarons"); // echarts theme
import resize from "@/views/dashboard/mixins/resize";

import "../../animate/animate.css";
//import '../../util/china.js'
import "echarts/map/js/world";
import "echarts/map/js/china";
import "echarts/map/js/china-contour";
import "echarts/map/js/province/anhui";
import "echarts/map/js/province/aomen";
import "echarts/map/js/province/hebei";
import "echarts/map/js/province/heilongjiang";
import "echarts/map/js/province/henan";
import "echarts/map/js/province/hubei";
import "echarts/map/js/province/hunan";
import "echarts/map/js/province/jiangsu";
import "echarts/map/js/province/jiangxi";
import "echarts/map/js/province/jilin";
import "echarts/map/js/province/liaoning";
import "echarts/map/js/province/neimenggu";
import "echarts/map/js/province/beijing";
import "echarts/map/js/province/ningxia";
import "echarts/map/js/province/qinghai";
import "echarts/map/js/province/shandong";
import "echarts/map/js/province/shanghai";
import "echarts/map/js/province/shanxi";
import "echarts/map/js/province/shanxi1";
import "echarts/map/js/province/sichuan";
import "echarts/map/js/province/taiwan";
import "echarts/map/js/province/tianjin";
import "echarts/map/js/province/xianggang";
import "echarts/map/js/province/chongqing";
import "echarts/map/js/province/xinjiang";
import "echarts/map/js/province/xizang";
import "echarts/map/js/province/yunnan";
import "echarts/map/js/province/zhejiang";
import "echarts/map/js/province/fujian";
import "echarts/map/js/province/gansu";
import "echarts/map/js/province/guangdong";
import "echarts/map/js/province/guangxi";
import "echarts/map/js/province/guizhou";
import "echarts/map/js/province/hainan";

import { parseQueryString, fIsUrL } from "../../util/urlUtil";
import { linkChart } from "../../util/LinkageChart";
import { chartApiBar, remoteChartApi,chartBIanalysis  } from "@/api/tool/datav/chartApi";

import { addOption } from "../../codegen/codegen";

import { mapBIanalysis } from "@/api/tool/datav/chartBI/chartMapBI";
import { getFormsource } from "@/api/tool/datav/formsource";

const animationDuration = 6000;
import VueEvent from "@/views/tool/datav/VueEvent";
import { websocketCommand } from "../../util/websocket.js";

export default {
  mixins: [resize],
  props: {
    className: {
      type: String,
      default: "chart"
    },
    width: {
      type: String,
      default: "100%"
    },
    height: {
      type: String,
      default: "100%"
    },
    chartOption: {
      type: Object
    },
    drawingList: {
      type: Array
    }
  },
  data() {
    return {
      chart: null,
      //dataOption: this.chartOption,
      timer: "",
      wsObj: null,
      wsFlag: false,
      wsTimer: "",
      wsValue: null,
      animate: this.className
    };
  },
  watch: {
    width() {
      this.$nextTick(() => {
        this.chart.resize();
      });
    },
    height() {
      //this.$nextTick(() => {
      this.chart.resize();
      //});
    },
    chartOption: {
      deep: true,
      handler(newVal) {
        this.setOptions(JSON.parse(JSON.stringify(newVal)));
      }
    },
    "chartOption.theme": {
      handler() {
        if (this.chart != null) {
          this.chart.dispose();
          this.chart = null;
          this.initChart();
        }
      }
    },
    "chartOption.timeout": {
      handler() {
        this.chart.dispose();
        this.chart = null;
        this.initChart();
      }
    },
    "chartOption.dataSourceType": {
      handler(value) {
        //切换数据源重新连接
        if (value !== "websocket") {
          this.wsFlag = false;
          //每次切换数据源恢复原来动画
          this.animate = this.className;
        }
        if (value !== "url") {
          clearTimeout(this.timer);
        } 
      }
    },
    "chartOption.interfaceKey": {
      handler(newValue, oldValue) {
        //初始化不创建连接，改变接口地址重新创建
        if (oldValue !== undefined && oldValue != "") {
          this.wsValue = null;
          this.closeWs();
          this.createWs();
          this.animate = this.className;
        }
      }
    },
    wsFlag: {
      handler(value) {
        if (!value) {
          this.wsValue = null;
          this.closeWs();
        }
      }
    },
    className: {
      handler(value) {
        this.animate = value;
      }
    }
  },
  mounted() {
    //this.$nextTick(() => {
    this.initChart();
    //});
  },
  beforeDestroy() {
    if (!this.chart) {
      return;
    }
    this.chart.dispose();
    this.chart = null;
    clearTimeout(this.timer);
    if (this.wsFlag) {
      this.closeWs();
    }
  },
  methods: {
    initChart() {
      this.chart = echarts.init(this.$el, "macarons");
      
      //判断是否开启定时器，当是访问url接口时候并且timeout不为0时候开启定时器
      if (this.timer != "") {
        clearTimeout(this.timer);
      }
      if (
        (this.chartOption.dataSourceType == 'url' || this.chartOption.dataSourceType == 'database') &&
        this.chartOption.timeout > 0
      ) {
        let timerTask = () => {
          this.setOptions(JSON.parse(JSON.stringify(this.chartOption)));
          this.timer = setTimeout(() => {
            timerTask();
          }, this.chartOption.timeout);
        };

        timerTask();
      }else{
        this.setOptions(JSON.parse(JSON.stringify(this.chartOption)));
      }
    },
    setOptions: async function(dataOption) {
      // console.log(dataOption)
      //初始化数据
      //如果不是静态数据就调用接口给staticDataValue赋值
      if (dataOption.dataSourceType == "url") {
        let paramJson = parseQueryString(dataOption.requestParameters);

        let interfaceURL = dataOption.interfaceURL;
        dataOption.staticDataValue = await chartApiBar(
          dataOption.requestMethod,
          interfaceURL,
          paramJson,
          dataOption.token
        );
        //console.log(paramJson);
      } else if (dataOption.dataSourceType == "database") {
        if (
          dataOption.database.executeSql != undefined &&
          dataOption.database.executeSql != ""
        ) {
          let result = [];
          if(dataOption.database.sqlType != 'custom'){
          
            result = await mapBIanalysis(dataOption.database);
          }else{
            result = await chartBIanalysis(dataOption.database);
          }
          if (result.code == 200) {
            dataOption.staticDataValue = result.data;
            //console.log(dataOption.staticDataValue);
          } else {
            alert("操作数据库错误");
          }
        }
      } else if (dataOption.dataSourceType == "form") {
        if (dataOption.formSource != undefined) {
          let response = await getFormsource(dataOption.formSource.id);
          dataOption.staticDataValue = JSON.parse(response.data.formData);
        }
      } else if (dataOption.dataSourceType == "websocket") {
        if (
          dataOption.interfaceKey != undefined &&
          dataOption.interfaceKey != ""
        ) {
          if (!this.wsFlag) {
            this.wsFlag = true;
            this.wsValue = null;
            this.createWs();
          }
          if (this.wsValue != null) {
            dataOption.staticDataValue = this.wsValue;
          }
        }
      }

      if (dataOption.animate != null) {
        //添加动画样式
        //animateUtil.addAnimate(dataOption.bindingDiv, dataOption.animate);
      }
      var color = ["#26587D", "#3BB3C4"];
      if (dataOption.isTopic == true) {
        if (this.chartOption.theme != null) {
          color = this.chartOption.theme.color;
        } else {
          color = color;
        }
      } else {
        color = color;
      }
  
      //let mapName = "china";
      let mapName = dataOption.mapName;
      let geoCoordMap = {};
      /*获取地图数据*/
      //myChart.showLoading();
      let mapFeatures = echarts.getMap(mapName).geoJson.features;
      //myChart.hideLoading();
      mapFeatures.forEach(function(v) {
        // 地区名称
        let name = v.properties.name;
        // 地区经纬度
        geoCoordMap[name] = v.properties.cp;
      });
      //console.log(data)
      let max = 500,
        min = 10; // todo
      let maxSize4Pin = 50,
        minSize4Pin = 20;

      let convertData = function(data) {
        let res = [];
        for (let i = 0; i < data.length; i++) {
          let geoCoord = geoCoordMap[data[i].name];
          if (geoCoord) {
            res.push({
              name: data[i].name,
              value: geoCoord.concat(data[i].value)
            });
          } else if (data[i].lng != undefined && data[i].lat != undefined) {
            res.push({
              name: data[i].name,
              value: [data[i].lng,data[i].lat,data[i].value]
            });
          }
        }
        //console.log(res)
        return res;
      };

      let seriesData = [
        {
          name: "map",
          type: "map",
          map: mapName,
          geoIndex: 0,
          aspectScale: 0.75, //长宽比
          selectMode: "single",
          showLegendSymbol: false, // 存在legend时显示
          label: {
            normal: {
              show: true
            },
            emphasis: {
              show: false,
              textStyle: {
                color: "#fff"
              }
            }
          }
        }
      ];
      /*
       * 判断是否需要添加散点图、气泡图和top5
       */
      if (dataOption.isScatter == true) {
        dataOption.scatterData.data = convertData(dataOption.staticDataValue);
        dataOption.scatterData.symbolSize = function(val) {
          return dataOption.scatterSize
            ? dataOption.scatterSize
            : val[2] / 10 > 100
            ? 100
            : val[2] / 10;
        };
        dataOption.scatterData.tooltip.formatter = function(val) {
          return val.name + ":" + val.value[2] + dataOption.suffix;
        };
        seriesData.push(dataOption.scatterData);
      }
      if (dataOption.isGeo == true) {
        dataOption.geoData.data = convertData(dataOption.staticDataValue);
        dataOption.geoData.symbolSize = function(val) {
          //console.log(val[2]);
          var a = (maxSize4Pin - minSize4Pin) / (max - min);
          var b = minSize4Pin - a * min;
          b = maxSize4Pin - a * max;
          return dataOption.popSize
            ? dataOption.popSize
            : a * val[2] + b > 200
            ? 200
            : a * val[2] + b;
        };

        dataOption.geoData.tooltip.formatter = function(val) {
          return val.name + ":" + val.value[2] + dataOption.suffix;
        };
        //选择气泡图形时，选择颜色
        if (dataOption.popORimg == "pop") {
          dataOption.geoData.symbol = "pin";
          dataOption.geoData.itemStyle.normal.color = dataOption.popColor
            ? dataOption.popColor
            : "rgba(216, 55, 55, 1)";
        }
        if (dataOption.popORimg == "img") {
          dataOption.geoData.symbol = "image://" + dataOption.popImg;
          dataOption.geoData.label.normal.show = false;
        }

        seriesData.push(dataOption.geoData);
      }
      if (dataOption.isTop == true) {
        //console.log("top5Data:", dataOption.top5Data.data);
        let topNum = dataOption.topNum;
        if (topNum > dataOption.staticDataValue.length) {
          topNum = dataOption.staticDataValue.length;
        }
        dataOption.top5Data.data = convertData(
          dataOption.staticDataValue
            .sort(function(a, b) {
              return b.value - a.value;
            })
            .slice(0, topNum)
        );
        dataOption.top5Data.symbolSize = function(val) {
          return dataOption.scatterSize ? dataOption.scatterSize : 10;
        };
        dataOption.top5Data.tooltip.formatter = function(val) {
          return val.name + ":" + val.value[2] + dataOption.suffix;
        };
        seriesData.push(dataOption.top5Data);
      }

      var option = {
        title: {
          text: dataOption.title.text, //主标题
          textStyle: {
            color: "#fff", //颜色
            fontWeight: dataOption.title.textStyle.fontWeight, // 粗细
            fontFamily: dataOption.title.textStyle.fontFamily, // 字体
            fontSize: dataOption.title.textStyle.fontSize, // 字号大小
            align: "center" //水平对齐
          },
          subtext: dataOption.title.subtext, //副标题
          subtextStyle: {
            //对应样式
            color: "#fff",
            fontWeight: dataOption.title.textStyle.fontWeight, // 粗细
            fontFamily: dataOption.title.textStyle.fontFamily, // 字体
            fontSize: dataOption.title.textStyle.fontSize - 5,
            align: "center"
          },
          x: dataOption.title.x,
          itemGap: 7
        },
        //tooltip: dataOption.tooltip,
        visualMap: dataOption.visualMap,
        tooltip: {
          trigger: "item",
          formatter: function(params) {
            //console.log(params.data)
            if (params.data) {
              var toolTiphtml = params.data.name + ":<br>" + params.data;
              return toolTiphtml;
            }
            return;
          }
        },
        geo: {
          show: true,
          map: mapName,
          label: {
            normal: {
              show: false
            },
            emphasis: {
              show: false
            }
          },
          roam: dataOption.roam,
          itemStyle: {
            normal: {
              // areaColor: "#031525",   //区域颜色
              // borderColor: "#3B5077", //描边颜色
              areaColor:
                dataOption.isTopic == true ? color[0] : dataOption.areaColor, //区域颜色
              borderColor:
                dataOption.isTopic == true ? color[1] : dataOption.borderColor //描边颜色
            },
            emphasis: {
              areaColor:
                dataOption.isTopic == true
                  ? color[2]
                  : dataOption.emphasisColor
                  ? dataOption.emphasisColor
                  : "#2B91B7"
            }
          }
        },
        series: seriesData,
        bindingType: "map",
        suffix: dataOption.suffix
      };

      //执行通用处理函数
      if(dataOption.customData != undefined && dataOption.customData != ""){
        try {
          option = (
          
            //里面为要处理的代码块
          eval(dataOption.customData) 
          
          )(
            option,
            dataOption.staticDataValue,
            this.$refs.chartDiv
          );
        } catch (error) {
          console.log(error)
        }
       } 
        //交互组件配置
      if(dataOption.interactData != undefined && dataOption.interactData != ""){
          try {
              option = (        
              //里面为要处理的代码块
              eval(dataOption.interactData)             
            )(
            option,
            dataOption.staticDataValue,
            this.$refs.chartDiv
            );
          } catch (error) {
            console.log(error)
          }               
       }     
      this.chart.setOption(option, true);

      addOption(dataOption.bindingDiv, option);

      //开启图表联动
      if (dataOption.isLink == true) {
        this.chart.off("click");
        this.chart.on("click", params => {
          if(params.data != undefined){
            //设置参数
            let arrObject = {
              seriesName: params.name,
              data: params.value[2]
            };
            let arrs = JSON.stringify(arrObject);
            //获取绑定的图表
            let bindList = this.chartOption.bindList;

            if (bindList.length > 0) {
              linkChart(dataOption.arrName, arrs, bindList, this.drawingList);
            }
          }
          
        });
      }
      // else{
      //   //关闭图表联动，取消echart点击事件
      //   this.chart.off('click');
      // }

      //开启图表下钻
      else if (dataOption.isDrillDown == true) {
        this.chart.off("click");
        this.chart.on("click", params => {
          if(params.data != undefined){
            //设置参数
            let arrObject = {
              seriesName: params.name,
              data: params.value[2]
            };
            
            let arrs = JSON.stringify(arrObject);

            //获取绑定的图表
            let drillDownChartOption = this.chartOption.drillDownChartOption;

            if (
              drillDownChartOption != undefined &&
              drillDownChartOption != null
            ) {
              this.$set(
                this.chartOption.drillDownChartOption.chartOption,
                "requestParameters",
                "drillParam=" + arrs
              );
              //发送下钻消息
              VueEvent.$emit(
                "drill_down_msg",
                this.chartOption.drillDownChartOption
              );
            }
          }

        });
      } else {
        //关闭图表联动，取消echart点击事件
        this.chart.off("click");
      }
      //开启远程图表控制
      if (dataOption.isRemote == true) {
        if (dataOption.remote != undefined && dataOption.remote != null) {
          this.chart.off("click");
          this.chart.on("click", params => {
            if(params.data != undefined){
              //设置参数
              let arrObject = {
                seriesName: params.name,
                data: params.value[2]
              };

              let remoteData = { ...dataOption.remote };
              remoteData.query = arrObject;
              //调用接口
              remoteChartApi(remoteData);
            }
          });
        }
      }
    },
    //  ws连接成功，后台返回的ws数据
    receiveMsg(e) {
      if (e.action == "chat") {
        // console.log('服务端推送',e);
        this.wsValue = JSON.parse(e.result);
        this.setOptions(JSON.parse(JSON.stringify(this.chartOption)));
      }
    },
    // 建立连接、发起ws请求，以心跳方式，向服务端发送数据
    createWs() {
      this.wsObj = new WebSocket(process.env.VUE_APP_WEBSOCKET);
      // 若为对象类型，以回调方式发送
      websocketCommand(
        this.wsObj,
        "create",
        5000,
        this.chartOption.interfaceKey,
        this.sendHeartBeat,
        this.receiveMsg,
        this.reconnectWs,
        this.wsWarning
      );
    },
    // 断网重连，需要处理的逻辑
    reconnectWs() {
      if (this.wsObj) {
        console.log("%c websocket_reconnect", "color:blue");
        this.createWs();
      }
    },
    // 以回调方式向服务端发送(对象类型的)心跳
    sendHeartBeat() {
      if (this.wsTimer != "") {
        clearTimeout(this.wsTimer);
      }

      let wsTimerTask = () => {
        console.log("发送心跳", "ping");
        let obj = { action: "keep", key: this.chartOption.interfaceKey };
        this.wsObj.send(JSON.stringify(obj));
        this.wsTimer = setTimeout(() => {
          wsTimerTask();
        }, parseInt(process.env.VUE_APP_WEBSOCKET_TIMEOUT));
        this.wsWarning();
      };

      wsTimerTask();
    },
    wsWarning() {
      //如果断开连接则显示组件警告动画并清除计数器
      if (this.wsObj.readyState == 3) {
        this.animate = "warning";
        clearTimeout(this.wsTimer);
      }
    },
    closeWs() {
      clearTimeout(this.wsTimer);
      websocketCommand(
        this.wsObj,
        "close",
        5000,
        this.chartOption.interfaceKey,
        this.sendHeartBeat,
        this.receiveMsg,
        this.reconnectWs,
        this.wsWarning
      );
      this.wsObj = null;
    }
  }
};
</script>
